package com.min.main.service;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.min.common.entity.R;
import com.min.common.util.GsonUtil;
import com.min.common.util.ShiroUtils;
import com.min.main.constant.RedisKey;
import com.min.main.constant.UserStatus;
import com.min.main.dao.UserDao;
import com.min.main.entity.UserEntity;
import com.min.main.form.LoginForm;
import com.min.main.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 用户表
 *
 * @author fengt
 * @date 2021-06-23 11:41:08
 */
@Service
@Slf4j
public class UserService extends ServiceImpl<UserDao, UserEntity> {

    //12小时后过期
    private final static int EXPIRE = 3600 * 12;

    @Autowired
    RedisUtils redis;

    @Autowired
    CaptchaService captchaService;

    @Autowired
    RoleUserService roleUserService;

    public UserEntity getByAccount(String account) {
        return this.getOne(Wrappers.lambdaQuery(UserEntity.class).eq(UserEntity::getAccount, account));
    }

    public R login(LoginForm s) {

        log.debug("登录参数：" + GsonUtil.toJson(s));

        boolean check = captchaService.validate(s.getUuid(), s.getCaptcha());
        if (!check) {
            return R.error("验证码不正确");
        }

        UserEntity user = this.getByAccount(s.getAccount());
        if (user == null) {
            return R.error("账号或密码不正确");
        }
        final Sha256Hash sha256Hash = new Sha256Hash(s.getPassword(), user.getSalt());

        if (!user.getPassword().equals(new Sha256Hash(s.getPassword(), user.getSalt()).toHex())) {
            return R.error("账号或密码不正确");
        }

        if (UserStatus.ENABLE != user.getStatus()) {
            return R.error("账号已被锁定,请联系管理员");
        }

        String token = IdUtil.fastSimpleUUID();
        redis.set(RedisKey.TOKEN + token, user, EXPIRE);
        ShiroUtils.getSession().setTimeout(EXPIRE);
        return R.ok()
                .put("token", token)
                .put("expire", EXPIRE)
                .put("account",user.getAccount())
                .put("username",user.getUsername())
                .put("photo", user.getAvatar());
    }

    public void logout(String token) {
        redis.delete(RedisKey.TOKEN + token);
        if (ShiroUtils.isLogin()) {
            SecurityUtils.getSubject().logout();
        }
    }

    public UserEntity getUserByToken(String token) {
        return redis.get(RedisKey.TOKEN + token, UserEntity.class);
    }

    public boolean saveOrUpdateWithRoles(UserEntity u) {

        if (roleUserService.checkBounds(u.getRoleIdList())) {
            return false;
        }

        if (u.getId() != null && u.getId() > 0L) {
            if (u.getRoleIdList() != null) {
                roleUserService.saveRoleUser(u.getId(), u.getRoleIdList());
            }
            this.updateById(u);
            return true;
        } else {
            if (this.save(u)) {
                if (u.getRoleIdList() != null) {
                    roleUserService.saveRoleUser(u.getId(), u.getRoleIdList());
                }
                return true;
            }
        }

        return false;

    }
}

